﻿using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// 快捷菜单特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class ContextMenuItemAttribute : Attribute
    {
        /// <summary>
        /// 快捷菜单特性
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="index">顺序</param>
        public ContextMenuItemAttribute(string name, int index)
        {
            Name = name;
            Index = index;
        }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// 顺序
        /// </summary>
        public int Index { get; private set; }

        /// <summary>
        /// 图标(16x16)(反射资源得到图片)
        /// </summary>
        public string IconName { get; set; }

        /// <summary>
        /// 选中
        /// </summary>
        public bool Checked { get; set; } = false;

        /// <summary>
        /// 显示
        /// </summary>
        public bool Visible { get; set; } = true;

        /// <summary>
        /// 使用
        /// </summary>
        public bool Enabled { get; set; } = true;

        /// <summary>
        /// 特性转换
        /// </summary>
        /// <param name="menu"></param>
        /// <param name="assembly"></param>
        /// <param name="command"></param>
        /// <returns></returns>
        internal MenuItem GetContextMenuItem(Menu menu, Assembly assembly, string command)
        {
            MenuItem mi = new MenuItem(Name);
            mi.Click += (sender, e) =>
            {
                Document doc = Application.DocumentManager.MdiActiveDocument;
                doc?.SendStringToExecute(((char)27) + command.Trim() + "\n", true, false, false);
            };

            if (!string.IsNullOrEmpty(IconName))
            {
                using (Stream icon = assembly.GetManifestResourceStream(IconName))
                {
                    if (icon != null)
                    {
                        mi.Icon = new Icon(icon);
                    }
                    else
                    {
                        throw new System.Exception($"{nameof(ContextMenuItemAttribute)}的属性{nameof(IconName)}:\"{IconName}\"路径错误");
                    }
                };
            }

            mi.Checked = Checked;
            mi.Visible = Visible;
            mi.Enabled = Enabled;

            menu.MenuItems.Add(mi);

            return mi;
        }
    }

    /// <summary>
    /// 快捷菜单
    /// </summary>
    public static class ContextMenuItemAtt
    {
        /// <summary>
        /// 添加类型中的快捷菜单项
        /// </summary>
        /// <param name="menu">子菜单</param>
        /// <param name="t">具有实现了<see cref="ContextMenuItemAttribute"/>和<see cref="CommandMethodAttribute"/>的方法的类型</param>
        /// <returns>菜单项列表</returns>
        public static MenuItem[] AddContextMenuItem(this Menu menu, Type t)
        {
            Assembly assembly = t.Assembly;

            MenuItem[] list = t.GetMethods().Select(x => new
            {
                ContextMenu = x.GetCustomAttributes(typeof(ContextMenuItemAttribute), false).OfType<ContextMenuItemAttribute>(),
                Command = x.GetCustomAttributes(typeof(CommandMethodAttribute), false).OfType<CommandMethodAttribute>(),
            }).Where(x => x.ContextMenu.Count() != 0 && x.Command.Count() != 0)
               .Select(x => new
               {
                   Command = x.Command.First().GlobalName,
                   ContextMenuItem = x.ContextMenu.First(),
               }).OrderBy(x => x.ContextMenuItem.Index).Select(x =>
               {
                   MenuItem menuItem = x.ContextMenuItem.GetContextMenuItem(menu, assembly, x.Command);

                   return menuItem;
               }).ToArray();

            return list;
        }
    }
}